#include "elevation_calculator.h"
#include <fstream>
#include <sstream>
#include <cmath>
#include <iostream>

ElevationCalculator::ElevationCalculator() : dataLoaded(false) {
}

ElevationCalculator::~ElevationCalculator() {
    // 清理资源
    elevationData.clear();
}

bool ElevationCalculator::loadElevationData(const std::string& filePath) {
    std::ifstream file(filePath);
    if (!file.is_open()) {
        std::cerr << "无法打开高程数据文件: " << filePath << std::endl;
        return false;
    }

    elevationData.clear();
    std::string line;
    
    // 假设数据格式为: 经度,纬度,高程
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::string token;
        double longitude, latitude, elevation;
        
        // 读取经度
        if (!std::getline(iss, token, ',')) continue;
        longitude = std::stod(token);
        
        // 读取纬度
        if (!std::getline(iss, token, ',')) continue;
        latitude = std::stod(token);
        
        // 读取高程
        if (!std::getline(iss, token)) continue;
        elevation = std::stod(token);
        
        elevationData.push_back(GeoPoint(longitude, latitude, elevation));
    }

    file.close();
    dataLoaded = !elevationData.empty();
    
    if (dataLoaded) {
        std::cout << "成功加载 " << elevationData.size() << " 个高程数据点" << std::endl;
    } else {
        std::cerr << "高程数据文件为空或格式错误" << std::endl;
    }
    
    return dataLoaded;
}

// 计算两点之间的距离
static double calculateDistance(double lon1, double lat1, double lon2, double lat2) {
    // 简化的距离计算（不考虑地球曲率，适用于小范围区域）
    double dLon = lon2 - lon1;
    double dLat = lat2 - lat1;
    return std::sqrt(dLon * dLon + dLat * dLat);
}

double ElevationCalculator::calculateElevation(double longitude, double latitude) {
    if (!dataLoaded || elevationData.empty()) {
        std::cerr << "高程数据未加载" << std::endl;
        return 0.0;
    }

    // 如果只有一个数据点，直接返回该点的高程
    if (elevationData.size() == 1) {
        return elevationData[0].elevation;
    }

    // 查找最近的两个点进行插值
    double minDistance1 = std::numeric_limits<double>::max();
    double minDistance2 = std::numeric_limits<double>::max();
    size_t nearestIndex1 = 0;
    size_t nearestIndex2 = 0;

    for (size_t i = 0; i < elevationData.size(); ++i) {
        double distance = calculateDistance(longitude, latitude, 
                                           elevationData[i].longitude, elevationData[i].latitude);
        
        if (distance < minDistance1) {
            minDistance2 = minDistance1;
            nearestIndex2 = nearestIndex1;
            minDistance1 = distance;
            nearestIndex1 = i;
        } else if (distance < minDistance2) {
            minDistance2 = distance;
            nearestIndex2 = i;
        }
    }

    // 使用线性插值计算高程
    return linearInterpolation(elevationData[nearestIndex1], 
                              elevationData[nearestIndex2], 
                              longitude, latitude);
}

double ElevationCalculator::linearInterpolation(const GeoPoint& p1, const GeoPoint& p2, 
                                               double longitude, double latitude) {
    // 计算目标点到p1的距离与p1-p2总距离的比例
    double totalDistance = calculateDistance(p1.longitude, p1.latitude, p2.longitude, p2.latitude);
    double targetDistance = calculateDistance(p1.longitude, p1.latitude, longitude, latitude);
    
    if (totalDistance == 0) {
        return p1.elevation; // 如果两点重合，返回其中一点的高程
    }
    
    double ratio = targetDistance / totalDistance;
    // 确保比例在0-1之间
    ratio = std::max(0.0, std::min(1.0, ratio));
    
    // 线性插值计算高程
    return p1.elevation + ratio * (p2.elevation - p1.elevation);
}

bool ElevationCalculator::isDataLoaded() const {
    return dataLoaded;
}